using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace HTCollections.Custom
{
    /// <summary>
    /// 自定义列表
    /// </summary>
    public sealed class FastList<T> : IEnumerable<T>
    {
        public T[] Data;
        public int Capacity;
        public int Length;

        public EqualityComparer<T> Comparer;

        public FastList()
        {
            Capacity = 4;
            Data = new T[Capacity];
            Length = 0;
            Comparer = EqualityComparer<T>.Default;
        }

        public FastList(int capacity)
        {
            Capacity = capacity;
            Data = new T[Capacity];
            Length = 0;
            Comparer = EqualityComparer<T>.Default;
        }

        public FastList(FastList<T> list)
        {
            Capacity = list.Capacity;
            Data = new T[Capacity];
            Length = list.Length;
            Comparer = list.Comparer;
            Array.Copy(list.Data, 0, Data, 0, Length);
        }

        public T this[int index]
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get
            {
                CollectionsUtil.CheckIndexInRange(index, Length);
                return Data[index];
            }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            set
            {
                CollectionsUtil.CheckIndexInRange(index, Length);
                Data[index] = value;
            }
        }

        /// <summary>
        /// 扩容
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Expend()
        {
            ArrayUtil.Resize(ref Data, Capacity = ArrayUtil.GetCapacity(Capacity));
        }

        /// <summary>
        /// 扩容
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Resize(int newCapacity)
        {
            Capacity = newCapacity;
            ArrayUtil.Resize(ref Data, newCapacity);
        }

        /// <summary>
        /// 添加元素
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int Add(T value)
        {
            int index = Length;
            if (Length == Capacity)
                ArrayUtil.Resize(ref Data, Capacity = ArrayUtil.GetCapacity(Capacity));
            Data[index] = value;
            Length++;
            return index;
        }

        /// <summary>
        /// 添加元素集合
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRange(FastList<T> other)
        {
            if (other.Length == 0) return;
            int newSize = Length + other.Length;
            if (newSize > Capacity)
                ArrayUtil.Resize(ref Data, Capacity = ArrayUtil.GetCapacity(newSize));
            Array.Copy(other.Data, 0, Data, Length, other.Length);
            Length = newSize;
        }

        /// <summary>
        /// 删除指定索引元素
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool RemoveAt(int index)
        {
            if (index < 0 || index >= Length) return false;
            Length--;
            Array.Copy(Data, index + 1, Data, index, Length - index);
            Data[Length] = default;
            return true;
        }

        /// <summary>
        /// 删除指定元素
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Remove(T value)
        {
            return RemoveAt(IndexOf(value));
        }

        /// <summary>
        /// 清空列表
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Clear()
        {
            if (Length == 0) return;
            Array.Clear(Data, 0, Length);
            Length = 0;
        }

        /// <summary>
        /// 查询元素索引
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int IndexOf(T value)
        {
            for (int i = 0, length = Length; i < length; i++)
            {
                if (Comparer.Equals(Data[i], value))
                    return i;
            }

            return -1;
        }

        /// <summary>
        /// 检测是否包含指定元素
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Contains(T value)
        {
            return IndexOf(value) >= 0;
        }

        /// <summary>
        /// 列表转数组
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T[] ToArray()
        {
            T[] newArray = new T[Length];
            Array.Copy(Data, 0, newArray, 0, Length);
            return newArray;
        }

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            return GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        Enumerator GetEnumerator()
        {
            return new Enumerator(this);
        }

        struct Enumerator : IEnumerator<T>
        {
            FastList<T> mList;
            int mIndex;

            public T Current
            {
                [MethodImpl(MethodImplOptions.AggressiveInlining)]
                get => mList[mIndex];
            }

            object IEnumerator.Current => Current;

            public Enumerator(FastList<T> list)
            {
                mList = list;
                mIndex = -1;
            }

            public bool MoveNext()
            {
                mIndex++;
                return mIndex < mList.Length;
            }

            public void Reset()
            {
                mIndex = -1;
            }

            public void Dispose()
            {
            }
        }
    }
}